package com.huangfu.learning.javabase.java.pattern.action.interpreter;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/8/16
 * Time: 19:13
 * Version: 1.0
 * Description:解释器模式：提供了评估语言的语法或表达式的方式。 不常用
 * 参考：https://blog.csdn.net/taozi8023/article/details/51457555
 * https://blog.csdn.net/wbwjx/article/details/52456114
 * <p>
 * 应用实例：编译器、运算表达式计算。
 * <p>
 * 关键代码：构件环境类，包含解释器之外的一些全局信息，一般是 HashMap。
 * <p>
 * 其中涉及到的角色有:
 * AbstractExpression: 抽象表达式,声明一个抽象的解释操作父类,定义一个抽象的解释方法,具体的实现由子类解释器完成/
 * TerminalExpression: 终结符表达式,实现文法中与终结符有关的解释操作,文法中每一个终结符都有一个具体的终结表达式与之对应
 * NonterminalExpression: 非终结符表达式,实现文法中与非终结符有关的解释操作
 * Context: 上下文环境类,包含解释器之外的全局信息
 * Client: 客户端,解析表达式,构建抽象语法树,执行具体的解释操作等.
 * <p>
 * 优点： 1、可扩展性比较好，灵活。 2、增加了新的解释表达式的方式。 3、易于实现简单文法。
 * 缺点： 1、可利用场景比较少。 2、对于复杂的文法比较难维护。 3、解释器模式会引起类膨胀。 4、解释器模式采用递归调用方法
 * <p>
 * 实例：
 * 如下我们通过对算术表达式的解释来看一个解释器模式的实现,
 * 如表达式m+n+p中,如果我们使用解释器模式对该表达式进行解释,那么m,n,p代表的三个字母可以看成是终结符号,而+代表的运算符则可以看成是非终结符号
 **/
public class InterpreterPattern {
    public static void main(String[] args) {
        Expression isMale = InterpreterPatternDemo.getMaleExpression();
        Expression isMarriedWoman = InterpreterPatternDemo.getMarriedWomanExpression();

        System.out.println("John is male? " + isMale.interpret("John"));
        System.out.println("Julie is a married women? "
                + isMarriedWoman.interpret("Married Julie"));
    }
}

interface Expression {
    boolean interpret(String context);
}

/**
 * 创建实现了上述接口的实体类。
 * 终止、and、or
 */
class TerminalExpression implements Expression {

    private String data;

    public TerminalExpression(String data) {
        this.data = data;
    }

    @Override
    public boolean interpret(String context) {
        if (context.contains(data)) {
            return true;
        }
        return false;
    }
}

class OrExpression implements Expression {

    private Expression expr1 = null;
    private Expression expr2 = null;

    public OrExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) || expr2.interpret(context);
    }
}

class AndExpression implements Expression {

    private Expression expr1 = null;
    private Expression expr2 = null;

    public AndExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) && expr2.interpret(context);
    }
}

/**
 * InterpreterPatternDemo 使用 Expression 类来创建规则，并解析它们。
 */
class InterpreterPatternDemo {

    //规则：Robert 和 John 是男性
    static Expression getMaleExpression() {
        Expression robert = new TerminalExpression("Robert");
        Expression john = new TerminalExpression("John");
        return new OrExpression(robert, john);
    }

    //规则：Julie 是一个已婚的女性
    static Expression getMarriedWomanExpression() {
        Expression julie = new TerminalExpression("Julie");
        Expression married = new TerminalExpression("Married");
        return new AndExpression(julie, married);
    }
}